package cn.zysheep.httpclient;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Apache client delete 请求
 *
 */
public class HttpDeleteTest {

    /**
     * htp put 请求与 post 请求操作步骤是一样的，完全类似 post.
     */
    @Test
    public void testDelete1() {
        String url = "http://localhost:8080/example/httpDelete?info=delete请求";
        CloseableHttpClient httpClient = null;
        HttpDelete httpDelete = null;
        CloseableHttpResponse httpResponse = null;
        try {
            //1、创建 CloseableHttpClient 同步请求对象
            httpClient = HttpClientBuilder.create().build();

            // 2、HttpPost(final String uri)：创建 http post 请求对象, 设置请求头信息
            httpDelete = new HttpDelete(url);

            // 3、CloseableHttpResponse execute(final HttpUriRequest request)：执行请求
            // 如果连接不上服务器，则抛出:java.net.ConnectException: Connection refused: connect
            httpResponse = httpClient.execute(httpDelete);

            // 4、获取响应结果, 状态码 200 表示请求成功
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            System.out.println("响应状态码：" + statusCode);
            if (statusCode == 200) {
                HttpEntity httpEntity = httpResponse.getEntity();
                // 使用指定的字符编码解析响应消息实体
                String feedback = EntityUtils.toString(httpEntity, "UTF-8");
                System.out.println("feedback：" + feedback);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            /**
             * consume(final HttpEntity entity)：确保实体内容已完全使用，并且内容流（如果存在）已关闭。
             *  httpResponse.close()：关闭此流并释放与之关联的所有系统资源。如果流已关闭，则调用此方法无效。
             */
            try {
                if (httpResponse != null) {
                    EntityUtils.consume(httpResponse.getEntity());
                    httpResponse.close();
                }
                //无论成功与否,都要释放连接并终止
                if (httpDelete != null && !httpDelete.isAborted()) {
                    httpDelete.releaseConnection();
                    httpDelete.abort();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * CloseableHttpAsyncClient 异步执行 http 请求
     */
    @Test
    public void testDelete2() {
        String url = "http://localhost:8080/example/httpDelete?info=delete请求";
        //1、创建 CloseableHttpAsyncClient 异步请求对象
        CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClientBuilder.create().build();

        // 2、HttpDelete(final String uri)：创建 http delete 请求对象, 设置请求头信息
        HttpDelete httpDelete = new HttpDelete(url);

        // 3、Future<HttpResponse> execute(final HttpUriRequest request,FutureCallback<HttpResponse> callback)：执行请求
        // 异步请求在执行之前需调用 start 方法
        // FutureCallback 是异步执行的回调接口
        httpAsyncClient.start();
        httpAsyncClient.execute(httpDelete, new FutureCallback<HttpResponse>() {
            @Override
            public void completed(HttpResponse result) {
                try {
                    System.out.println("成功：" + result);
                    String feedback = EntityUtils.toString(result.getEntity(), "UTF-8");
                    System.out.println("feedback：" + feedback);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void failed(Exception ex) {
                //比如对方服务没启动，连接失败，就会进这里
                System.out.println("失败：" + ex);
            }

            @Override
            public void cancelled() {
                System.out.println("取消");
            }
        });
        try {
            TimeUnit.SECONDS.sleep(5);//主线程阻塞5秒，让异步执行完成.
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
